package com.casic.ops.runner.pipeline.node;

import com.alibaba.fastjson.JSON;
import com.casic.ops.entity.domain.ApplicationVcsDO;
import com.casic.ops.entity.domain.MachineInfoDO;
import com.casic.ops.entity.dto.pipeline.datastructure.Logger.NodeLogger;
import com.casic.ops.entity.dto.pipeline.datastructure.context.DefaultResult;
import com.casic.ops.entity.dto.pipeline.datastructure.context.Result;
import com.casic.ops.entity.dto.pipeline.datastructure.executecontext.PipelineExecuteContext;
import com.casic.ops.entity.dto.pipeline.datastructure.node.PipelineNodeConfigInfo;
import com.casic.ops.runner.pipeline.nodeconfiginfo.StartExecutableNodeConfigInfo;
import com.casic.ops.service.api.ApplicationVcsService;
import com.casic.ops.service.api.MachineInfoService;
import com.casic.ops.utils.ValueMix;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jose4j.lang.StringUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 流水线执行开始节点，目前该节点暂不执行，后面可以优化，例如在开始节点配置拉取代码、配置执行机器、配置触发方式（定时执行，提交代码执行，webhook方式）
 * @author cww
 * @date 2022/6/20
 */
@Service
@Slf4j
public class StartExecutableNode extends AbstractExecutableNode {

    @Resource
    private MachineInfoService machineInfoService;
    @Resource
    private ApplicationVcsService applicationVcsService;
    @Override
    public Result execute(PipelineExecuteContext context,String nodeUuid) {
        int statusCode = -1;
        //获取节点执行记录对象
        NodeLogger logger = (NodeLogger) context.getAttributes(nodeUuid+ "logger");
        logger.setNodeName("开始");
        DefaultResult defaultResult = new DefaultResult();
        //获取开始节点的配置信息
        PipelineNodeConfigInfo pipelineNodeConfigInfo = (PipelineNodeConfigInfo) context.getAttributes(nodeUuid);
        try {
            StartExecutableNodeConfigInfo nodeConfigInfo = JSON.parseObject(pipelineNodeConfigInfo.getInfo(), StartExecutableNodeConfigInfo.class);
            //给上下文设置开始节点的机器，如果后续运行节点没有选机器，则用开始节点的机器
            context.setAttributes("machineId", nodeConfigInfo.getMachineId());
            //获取机器实体类
            MachineInfoDO machineInfoDO = machineInfoService.selectById(nodeConfigInfo.getMachineId());
            //获取代码仓实体对象
            ApplicationVcsDO applicationVcsDO = applicationVcsService.selectById(nodeConfigInfo.getVcsId());
            //获取代码存放路径
            String path = nodeConfigInfo.getPath();
            //获取代码分支 此时的分支一般是 orion/master这种各种，要字符串切割获取到master
            String branch = nodeConfigInfo.getBranch();
            String realBranch = Arrays.asList(branch.split("/")).get(1);
            //拼接命令,切换到对应目录下
            String changeCodePathCommand = "cd " + path;
            //拉取代码前，先删除原来的代码
            List<String> tempPath = Arrays.asList(applicationVcsDO.getVscUrl().split("/"));
            //获取代码仓的目录名称，xxx.git
            String codeFolder = tempPath.get(tempPath.size() - 1);
            List<String> tempFolder = Arrays.asList(StringUtils.split(codeFolder, "."));
            String realFolder = tempFolder.get(0);
            //拉取代码前，先删除原来代码命令 例如删除 rm -rf /root/ops
            String deleteCodeCommand = "rm -rf " + path + "/" + realFolder;
            //拼接命令，输入git用户名
            String userName = applicationVcsDO.getVscUsername();
            //拼接命令，输入git用户密码
            String passWord = ValueMix.decrypt(applicationVcsDO.getVcsPassword());
            //拼接命令，根据代码分支拉取代码
            String cloneCodeCommand = "git clone " + "-b " + realBranch + " " + applicationVcsDO.getVscUrl();
            //剔除删库跑路的命令
            if (!deleteCodeCommand.equals("rm -rf /*")) {
                statusCode = shell(logger, context, machineInfoDO, deleteCodeCommand, changeCodePathCommand, cloneCodeCommand);
            } else {
                statusCode = shell(logger, context, machineInfoDO, changeCodePathCommand, cloneCodeCommand);
            }
        }catch (Exception e){
            String errorMessage="该节点配置信息为空，请先配置该节点信息"+"\r\n";
            ErrorHandle(e,logger,errorMessage);
        }
        log.info("{}节点执行完成", getName());


        defaultResult.add("status", statusCode);
        return defaultResult;
    }
    /**
     * 此方法返回的name是和pipeline_node_template里面节点的name是对应的，如果要修改，请同时去数据库里面，把对应的一条数据的name也改成一致的
     * @return
     */
    @Override
    public String getName() {
        return "START";
    }
}
